#include "stdafx.h"
#include "Node.h"
#include "Diskpage.h"
#include <iostream>
//#include <fstream.h>
#include <stdlib.h>

using namespace std;

//Constructor passed filename of destination
Diskpage::Diskpage(){
	skipIndex = 0;
	writeIndex = 0;
}
Diskpage::Diskpage(char *name, int index)
{
    filename=name;
	skipIndex=index;
	writeIndex = 0;
}

//Writes Array of Records to Diskpage in raw form
int Diskpage::writedp()
{
	//ofstream outRecord(filename, ios::app); Depriciated Code
	ofstream outArbRecord(filename, ios::app); //Integrating the ArbRecord
	 
     if(!outRecord)
     {
         cerr <<"File could not be opened" <<endl;
         return -1;
     }
	 
	 //outRecord.seekp(writeIndex * sizeof(Record));

     /*for(int i=0;i<7;i++)
	 {
         outRecord.write(reinterpret_cast<const char *>(&Rlist[i]),sizeof(Record));
		 writeIndex += 1;
     }*/

	 for(int j=0;j<7;j++)
	 {
		 //iterate through the ArbRecord
		 for(int k=0;k<Alist[j].getNodeNumber();k++)
		 {
			 Node temp = Alist[j].getNode(k);
			 int temp_i = temp.getValueI();
			 double temp_r = temp.getValueR();
			 char temp_c = temp.getValueC();
			 char * temp_s = temp.getValueS();
			 
			 switch(temp.getDataType())
			 {
			 case 'A':
				 outArbRecord.write(reinterpret_cast<const char *>(&temp_i), sizeof(temp_i));
				 break;
			 case 'B':
				 outArbRecord.write(reinterpret_cast<const char *>(&temp_r), sizeof(temp_r));
				 break;
			 case 'C':
				 outArbRecord.write(reinterpret_cast<const char *>(&temp_c), sizeof(temp_c));
				 break;
			 case 'D':
				 outArbRecord.write(reinterpret_cast<const char *>(temp_s), 30);
				 break;
			 default:
				 //
				 break;
			 }
		 }
	 }

	 //outRecord.close(); Depriciated
	 outArbRecord.close();

     return 0;
}    

//Reads first line of file
char* Diskpage::readHeader()
{
     ifstream inArbRecord(filename, ios::in);
     if(!inArbRecord){cerr << "File could not be opened" <<endl;}     //Tried returning null couldn't get it to work though

	 int length = 0;
	 int char_count = 0;
	 //char * header = "EMPTY";
	 char * header_static = new char[500];

	 for(int i=0;i<500;i++)
	 {
		 header_static[i] = 32;
	 }

	 char length_char[10] = "         ";
	 char temp_description[30];
	 char tempchar;

	 inArbRecord.read(reinterpret_cast< char *>(&length), sizeof(length));

	 if(length != 0)
	 {

		 itoa(length,length_char,10);

		 for(int i=0; i<10; i++)
		 {
			 if(length_char[i] > 32)
			 {
				 header_static[char_count++] = length_char[i];
			 }
		 }

		 header_static[char_count++] = 32;

		 for(int i=0;i<length;i++)
		 {
			 inArbRecord.read(reinterpret_cast<char *>(&temp_description), 30);
			 inArbRecord.read(reinterpret_cast<char *>(&tempchar), sizeof(tempchar));
			 for(int j=0; j<sizeof(temp_description); j++)
			 {
				 if(temp_description[j] > 32)
				 {
					 header_static[char_count++] = temp_description[j];
				 }
			 }
			 header_static[char_count++] = 32;
			 header_static[char_count++] = tempchar;
			 header_static[char_count++] = 32;
			 /*header_static += (*temp_description);
			 header_static += 32;
			 header_static += tempchar;
			 header_static += 32;*/
		 }

		 /*int sizeOfRecord;
		 int index = 0;
		 char* buffer;*/
		 /*char temp[MAX_LENGTH];*/

		 /*inRecord.getline(buffer,MAX_LENGTH);
		 inRecord.close();*/

		 /*while(buffer[index] != ' ') {
			  temp[index] = buffer[index];
			  index++;
		 }

		 sizeOfRecord = atoi(temp);*/

		 //header = header_static;
	 }
	 inArbRecord.close();
     return header_static;
}

int Diskpage::writeHeader(Node nodes[100])
{
	ofstream outArbRecord(filename, ios::app); //Integrating the ArbRecord
	 
     if(!outRecord)
     {
         cerr <<"File could not be opened" <<endl;
         return -1;
     }

	 int count = 0;

	 for(int i=0;i<100;i++)
	 {
		 if(nodes[i].used)
		 {
			 count++;
		 }
	 }

	 outArbRecord.write(reinterpret_cast<const char *>(&count), sizeof(count));

 	 //iterate through the nodes
	 for(int k=0;k<count;k++)
	 {
		 Node temp = nodes[k];
		 char * description = temp.getDescription();
		 char dt = temp.getDataType();
		 outArbRecord.write(reinterpret_cast<const char *>(description), 30);
		 outArbRecord.write(reinterpret_cast<const char *>(&dt), sizeof(dt));
	 }

	 //outRecord.close(); Depriciated
	 outArbRecord.close();

	 return 0;
}

//Reads raw Records and converts to record form
int Diskpage::readdp(int header_count, int header_length, int record_length, Node header_nodes[100])
{
     ifstream inArbRecord(filename,ios::in);
     if(!inArbRecord){cerr << "File could not be opened" <<endl; return -1;}
     
	 inArbRecord.seekg(((skipIndex * record_length) + header_length), ios::beg);
     
	 for(int i=0; i<7;i++)
     {
             for(int j=0; j<header_count; j++)
			 {
				 int temp_i = 0;
				 double temp_r = 0;
				 char temp_c = 0;
				 char temp_s[30] = "                             ";
				 switch(header_nodes[j].getDataType())
				 {
					 case 'A':
						 inArbRecord.read(reinterpret_cast<char *>(&temp_i), sizeof(temp_i));
						 Alist[i].setNode(j, header_nodes[j].getDescription(), header_nodes[j].getDataType(), temp_i);
						 break;
					 case 'B':
						 inArbRecord.read(reinterpret_cast<char *>(&temp_r), sizeof(temp_r));
						 Alist[i].setNode(j, header_nodes[j].getDescription(), header_nodes[j].getDataType(), temp_r);
						 break;
					 case 'C':
						 inArbRecord.read(reinterpret_cast<char *>(&temp_c), sizeof(temp_c));
						 Alist[i].setNode(j, header_nodes[j].getDescription(), header_nodes[j].getDataType(), temp_c);
						 break;
					 case 'D':
						 inArbRecord.read(reinterpret_cast<char *>(&temp_s), 30);
						 Alist[i].setNode(j, header_nodes[j].getDescription(), header_nodes[j].getDataType(), temp_s);
						 break;
					 default:
						 //
						 break;
				 }
			 }
             //Rlist[i].display();
     }
	 inArbRecord.close();

     return 0;
}
//Search function for raw data file
ArbRecord Diskpage::find(int n, int header_count, int header_length, int record_length, Node header_nodes[100])
{
       /*Record R1;
	   fstream RecordFile;
       RecordFile.seekg((n-1)*sizeof(Record),ios::beg);
       RecordFile.read(reinterpret_cast<char *>(&R1),sizeof(Record));*/
	   if((n > skipIndex + 6) || ( (n-1) < skipIndex))
	   {
		   skipIndex = n;
		   readdp(header_count, header_length, record_length, header_nodes);
	   }
       return Alist[(n-1) % 7];
}
//Used to set the Record list for a diskpage
void Diskpage::setRlist(int i, Record R)
{
     Rlist[i]=R;
}

void Diskpage::setAlist(int i, ArbRecord AR)
{
	Alist[i] = AR;
}

//Empties the diskpage by setting all records to an empty record.
void Diskpage::empty()
{
	/*for(int i = 0; i < 7; i++)
	{
		Rlist[i].setID(0);
	}*/

	for(int i=0;i<7;i++)
	{
		Alist[i].used = false;
	}
}

//checks to see if the diskpage is full.
bool Diskpage::isFull()
{
	/*for(int i = 0; i < 7; i++)
	{
		if(Rlist[i].getID() == 0)
		{
			return false;
		}
	}*/

	for(int i = 0; i < 7; i++)
	{
		if(Alist[i].used == false)
		{
			return false;
		}
	}

	return true;
}